package com.suyafei.service.impl;

import com.alibaba.fastjson.JSON;
import com.suyafei.constant.CacheKey;
import com.suyafei.enums.BizCodeEnum;
import com.suyafei.exception.BizException;
import com.suyafei.interceptor.LoginIntercept;
import com.suyafei.model.LoginUser;
import com.suyafei.request.CartItemRequest;
import com.suyafei.service.CartService;
import com.suyafei.service.ProductService;
import com.suyafei.vo.CartItemVO;
import com.suyafei.vo.CartVO;
import com.suyafei.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: suyafei-1024-shop
 * @description
 * @author: luffy
 * @create: 2021-03-10 14:13
 */
@Service
@Slf4j
public class CartServiceImpl implements CartService {


    @Autowired
    private ProductService productService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 删除购物项
     * @param productId
     */
    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        myCartOps.delete(productId);
    }

    /**
     * 用于订单服务，确认订单，获取对应的商品项详情信息，清空购物车商品数据
     *
     * @param productIdList
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderCartItems(List<Long> productIdList) {
        List<CartItemVO> cartItemVOS = buildCartItem(true);

        List<CartItemVO> resultList = cartItemVOS.stream().filter(obj -> {
            if (productIdList.contains(obj.getProductId())) {
                this.deleteItem(obj.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 修改
     * @param cartItemRequest
     */
    @Override
    public void changeItemNum(CartItemRequest cartItemRequest) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        Object object = myCartOps.get(cartItemRequest.getProductId());
        if (object == null) {
            throw new BizException(BizCodeEnum.CART_FAIL);
        }
        CartItemVO cartItemVO = JSON.parseObject((String) object, CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
        myCartOps.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));

    }

    /**
     * 获取购物车
     * @return
     */
    @Override
    public CartVO getMyCart() {
        //获取全部购物项目
        List<CartItemVO> cartItemVOList = buildCartItem(false);

        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOList);
        return cartVO;
    }

    /**
     * 获取最新的购物项
     *
     * @param latestPrice 是否获取最新价格
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean latestPrice) {

        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();

        List<Object> itemList = myCartOps.values();

        List<CartItemVO> cartItemVOList = new ArrayList<>();

        List<Long> productIdList = new ArrayList<>();
        for (Object item : itemList) {

            CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
            cartItemVOList.add(cartItemVO);
            productIdList.add(cartItemVO.getProductId());
        }
        //查询最新的商品价格
        if (latestPrice) {
            setProductLatestPrice(cartItemVOList, productIdList);
        }

        return cartItemVOList;
    }

    /**
     * 设置商品的最新价格
     *
     * @param cartItemVOList
     * @param productIdList
     */
    private void setProductLatestPrice(List<CartItemVO> cartItemVOList, List<Long> productIdList) {
        //批量查询
        List<ProductVO> productVOList = productService.findProductByIdBatch(productIdList);

        //分组
        Map<Long, ProductVO> maps = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        cartItemVOList.stream().forEach(item->{
            ProductVO productVO = maps.get(item.getProductId());
            item.setProductTitle(productVO.getTitle());
            item.setProductImg(productVO.getCoverImg());
            item.setAmount(productVO.getAmount());

        });

    }

    /**
     * 清空购物车
     */
    @Override
    public void clear() {
        redisTemplate.delete(getCartKey());
    }


    /**
     * 添加商品到购物车
     *
     * @param cartItemRequest
     */
    @Override
    public void addToCart(CartItemRequest cartItemRequest) {

        long productId = cartItemRequest.getProductId();
        Integer buyNum = cartItemRequest.getBuyNum();
        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();

        Object cacheObj = myCart.get(productId);

        String result = "";

        if (cacheObj != null) {
            result = (String) cacheObj;
        }

        if (StringUtils.isBlank(result)) {
            //不存在就新建一个商品
            CartItemVO cartItemVO = new CartItemVO();

            ProductVO productVO = productService.findDetailById(productId);

            if (productVO == null) {
                throw new BizException(BizCodeEnum.CART_FAIL);
            }
            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setProductId(productId);
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());


            myCart.put(productId, JSON.toJSONString(cartItemVO));

        }else {
            //存在商品，修改数量
            CartItemVO cartItem = JSON.parseObject(result, CartItemVO.class);
            cartItem.setBuyNum(cartItem.getBuyNum() + buyNum);
            myCart.put(productId, JSON.toJSONString(cartItem));
        }


    }

    /**
     * 抽取我的购物车，通用方法
     *
     * @return
     */
    private BoundHashOperations<String, Object, Object> getMyCartOps() {
        String cartKey = getCartKey();
        return redisTemplate.boundHashOps(cartKey);

    }
    /**
     * 购物车key
     * @return`
     */
    private String getCartKey() {

        LoginUser loginUser = LoginIntercept.threadLocal.get();
        String cacheKey = String.format(CacheKey.CART_KEY, loginUser.getId());

        return cacheKey;


    }
}
